package com.chengqs.rapid.client.support.dubbo;

import com.chengqs.rapid.client.core.AbstractClientRegistryManager;
import com.chengqs.rapid.client.core.RapidAnnotationScanner;
import com.chengqs.rapid.client.core.autoconfigure.RapidProperties;
import com.chengqs.rapid.common.config.ServiceDefinition;
import com.chengqs.rapid.common.config.ServiceInstance;
import com.chengqs.rapid.common.constants.BasicConst;
import com.chengqs.rapid.common.constants.RapidConst;
import com.chengqs.rapid.common.util.NetUtils;
import com.chengqs.rapid.common.util.TimeUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.spring.ServiceBean;
import org.apache.dubbo.config.spring.context.event.ServiceBeanExportedEvent;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;

import javax.annotation.PostConstruct;
import java.util.HashSet;
import java.util.Set;

/**
 * <B>主类名称：</B>DubboClientRegistryManager<BR>
 * <B>概要说明：</B>enter<BR>
 *
 * @author: chengqs
 * @create: 2025-03-15 23:07:17
 **/
@Slf4j
public class Dubbo27ClientRegistryManager
        extends AbstractClientRegistryManager
        implements EnvironmentAware, ApplicationListener<ApplicationEvent> {

    public Dubbo27ClientRegistryManager(RapidProperties rapidProperties) throws Exception {
        super(rapidProperties);
    }

    private Environment environment;

    private static final Set<Object> uniqueBeanSet = new HashSet<>();

    @PostConstruct
    private void init() {
        String port = environment.getProperty(DubboConstants.DUBBO_PROTOCOL_PORT);
        if(StringUtils.isEmpty(port)) {
            log.error("Rapid Dubbo服务未启动");
            return;
        }
        whetherStart = true;
    }

    @Override
    public void onApplicationEvent(ApplicationEvent applicationEvent) {
        if(!whetherStart) {
            return;
        }
        if(applicationEvent instanceof ServiceBeanExportedEvent) {
            ServiceBean<?> serviceBean = ((ServiceBeanExportedEvent)applicationEvent).getServiceBean();
            try {
                registryServiceBean(serviceBean);
            } catch (Exception e) {
                log.error("Rapid Dubbo 注册服务ServiceBean 失败，ServiceBean = {}", serviceBean, e);
            }
        } else if(applicationEvent instanceof ApplicationStartedEvent){
            //	START:::
            System.out.println("******************************************");
            System.out.println("**        Rapid Dubbo Started           **");
            System.out.println("******************************************");
        }
    }

    @Override
    public void setEnvironment(Environment environment) {
        this.environment = environment;
    }

    /**
     * 注册Dubbo服务：从ServiceBeanExportedEvent获取ServiceBean对象
     * @param serviceBean
     * @throws Exception
     */
    private void registryServiceBean(ServiceBean<?> serviceBean) throws Exception {
        Object bean = serviceBean.getRef();
        if(uniqueBeanSet.add(bean)) {
            ServiceDefinition serviceDefinition = RapidAnnotationScanner.getInstance().scanBuilder(bean, serviceBean);
            if(serviceDefinition != null) {
                //	设置环境
                serviceDefinition.setEnvType(getEnv());
                //	注册服务定义
                registerServiceDefinition(serviceDefinition);

                //	注册服务实例：
                ServiceInstance serviceInstance = new ServiceInstance();
                String localIp = NetUtils.getLocalIp();
                int port = serviceBean.getProtocol().getPort();
                String serviceInstanceId = localIp + BasicConst.COLON_SEPARATOR + port;
                String address = serviceInstanceId;
                String uniqueId = serviceDefinition.getUniqueId();
                String version = serviceDefinition.getVersion();

                serviceInstance.setServiceInstanceId(serviceInstanceId);
                serviceInstance.setUniqueId(uniqueId);
                serviceInstance.setAddress(address);
                serviceInstance.setWeight(RapidConst.DEFAULT_WEIGHT);
                serviceInstance.setRegisterTime(TimeUtil.currentTimeMillis());
                serviceInstance.setVersion(version);

                registerServiceInstance(serviceInstance);
            }
        }
    }
}
